package com.neuedu.service.impl;

import com.alipay.api.AlipayResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.demo.trade.model.ExtendParams;
import com.alipay.demo.trade.model.GoodsDetail;
import com.alipay.demo.trade.model.builder.AlipayTradePrecreateRequestBuilder;
import com.alipay.demo.trade.model.result.AlipayF2FPrecreateResult;
import com.alipay.demo.trade.service.AlipayTradeService;
import com.alipay.demo.trade.service.impl.AlipayTradeServiceImpl;
import com.alipay.demo.trade.utils.ZxingUtils;
import com.neuedu.common.JSONData;
import com.neuedu.dao.OrderItemMapper;
import com.neuedu.dao.OrderMapper;
import com.neuedu.dao.PayInfoMapper;
import com.neuedu.pojo.Order;
import com.neuedu.pojo.OrderItem;
import com.neuedu.pojo.PayInfo;
import com.neuedu.service.PayService;
import com.neuedu.utils.AliOssUtils;
import com.neuedu.utils.FileUtils;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service(value = "payService")
public class PayServiceImpl implements PayService {
    Logger log = LoggerFactory.getLogger(PayServiceImpl.class);
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderItemMapper orderItemMapper;
    @Autowired
    private AliOssUtils aliOssUtils;
    @Autowired
    private PayInfoMapper payInfoMapper;

    public JSONData pay(Integer userId, Long orderNo, String path) {
        //-需要返回：订单号 与 二维码
        Map<String,String> map = new HashMap<String, String>();
        //-1、先判断订单号，是否存在
        Order order = orderMapper.selOrderByUserIdAndOrderNo(userId, orderNo);
        if(order==null){
            return JSONData.buildError("用户没有此订单号，请核对后，再进行操作");
        }
        map.put("orderNo",order.getOrderNo()+"");
        //-2、将订单的相关信息，发送到沙箱环境，生成对应的支付二维码
        //二维码的地址显示到web页面上
        String er_path = this.trade_precreate(order,userId,path);
        map.put("ermapath",er_path);
        return JSONData.buildSuccess(map);
    }

    // 测试当面付2.0生成支付二维码
    public String trade_precreate(Order order,Integer userId,String path) {
        String upload = "";
        // (必填) 商户网站订单系统中唯一订单号，64个字符以内，只能包含字母、数字、下划线，
        // 需保证商户系统端不能重复，建议通过数据库sequence生成，
        String outTradeNo = order.getOrderNo()+"";

        // (必填) 订单标题，粗略描述用户的支付目的。如“xxx品牌xxx门店当面付扫码消费”
        String subject = "睿乐购门店当面付扫码消费，此订单号为："+order.getOrderNo();

        // (必填) 订单总金额，单位为元，不能超过1亿元
        // 如果同时传入了【打折金额】,【不可打折金额】,【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】
        String totalAmount = order.getPayment().toString();

        // (可选) 订单不可打折金额，可以配合商家平台配置折扣活动，如果酒水不参与打折，则将对应金额填写至此字段
        // 如果该值未传入,但传入了【订单总金额】,【打折金额】,则该值默认为【订单总金额】-【打折金额】
        String undiscountableAmount = "0";

        // 卖家支付宝账号ID，用于支持一个签约账号下支持打款到不同的收款账号，(打款到sellerId对应的支付宝账号)
        // 如果该字段为空，则默认为与支付宝签约的商户的PID，也就是appid对应的PID
        String sellerId = "";

        // 订单描述，可以对交易或商品进行一个详细地描述，比如填写"购买商品2件共15.00元"
        String body = "此订单的总金额为："+order.getPayment().toString();

        // 商户操作员编号，添加此参数可以为商户操作员做销售统计
        String operatorId = "test_operator_id";

        // (必填) 商户门店编号，通过门店号和商家后台可以配置精准到门店的折扣信息，详询支付宝技术支持
        String storeId = "test_store_id";

        // 业务扩展参数，目前可添加由支付宝分配的系统商编号(通过setSysServiceProviderId方法)，详情请咨询支付宝技术支持
        ExtendParams extendParams = new ExtendParams();
        extendParams.setSysServiceProviderId("2088100200300400500");

        // 支付超时，定义为120分钟
        String timeoutExpress = "120m";

        // 商品明细列表，需填写购买商品详细信息，
        List<GoodsDetail> goodsDetailList = new ArrayList<GoodsDetail>();

        //-查询订单详情：(order_item=>userid/orderNo)
        List<OrderItem> orderItemList = orderItemMapper.queryOrderItemsByUserIdAndOrderNo(userId, order.getOrderNo());
        for(OrderItem orderItem:orderItemList){
            GoodsDetail goods = GoodsDetail.newInstance(orderItem.getProductId()+"",orderItem.getProductName(),orderItem.getCurrentUnitPrice().longValue(),orderItem.getQuantity());
            goodsDetailList.add(goods);
        }

        // 创建扫码支付请求builder，设置请求参数
        AlipayTradePrecreateRequestBuilder builder = new AlipayTradePrecreateRequestBuilder()
                .setSubject(subject).setTotalAmount(totalAmount).setOutTradeNo(outTradeNo)
                .setUndiscountableAmount(undiscountableAmount).setSellerId(sellerId).setBody(body)
                .setOperatorId(operatorId).setStoreId(storeId).setExtendParams(extendParams)
                .setTimeoutExpress(timeoutExpress)
                //支付宝服务器主动通知商户服务器里指定的页面http路径,根据需要设置
                //支付宝回调地址：地址+请求
                .setNotifyUrl("http://neuedushopping.free.idcfengye.com/callback")
                .setGoodsDetailList(goodsDetailList);

        AlipayTradeService tradeService = new AlipayTradeServiceImpl.ClientBuilder().build();
        AlipayF2FPrecreateResult result = tradeService.tradePrecreate(builder);
        switch (result.getTradeStatus()) {
            case SUCCESS:
                log.info("支付宝预下单成功: )");

                AlipayTradePrecreateResponse response = result.getResponse();
                dumpResponse(response);

                //先判断path是否存在
                File pathFile = new File(path);
                if(!pathFile.exists()){
                    pathFile.setWritable(true);
                    pathFile.mkdirs();
                }

                // 需要修改为运行机器上的路径(生成支付二维码)
                String filePath = String.format(path+"/qr-%s.png",response.getOutTradeNo());
                String qrFileName = String.format("qr-%s.png",response.getOutTradeNo());
                log.info("filePath:" + filePath);
                ZxingUtils.getQRCodeImge(response.getQrCode(), 256, filePath);

                //IO:图片的存储
                File targetFile = new File(path,qrFileName);
                // File==>FileItem==>MultipartFile
                FileItem fileItem = FileUtils.createFileItem(targetFile,targetFile.getName());
                MultipartFile multipartFile = new CommonsMultipartFile(fileItem);
                //二维码的路径：（在web页面上进行显示）
                upload = aliOssUtils.upload(multipartFile);

                break;

            case FAILED:
                log.error("支付宝预下单失败!!!");
                break;

            case UNKNOWN:
                log.error("系统异常，预下单状态未知!!!");
                break;

            default:
                log.error("不支持的交易状态，交易返回异常!!!");
                break;
        }
        return upload;
    }
    // 简单打印应答
    private void dumpResponse(AlipayResponse response) {
        if (response != null) {
            log.info(String.format("code:%s, msg:%s", response.getCode(), response.getMsg()));
            if (StringUtils.isNotEmpty(response.getSubCode())) {
                log.info(String.format("subCode:%s, subMsg:%s", response.getSubCode(),
                        response.getSubMsg()));
            }
            log.info("body:" + response.getBody());
        }
    }

    public JSONData callback(Map<String, String> params,Integer userId) {
        String orderNo = params.get("out_trade_no");
        Order order = orderMapper.selOrderByUserIdAndOrderNo(userId,Long.parseLong(orderNo));
        if(order==null){
            return JSONData.buildError("无此订单，处理失败");
        }
        //-判断：支付状态
        String tradeStatus = params.get("trade_status");
        //-只判断是否交易成功:关闭
        if("TRADE_SUCCESS".equals(tradeStatus)){
            //-20:已付款
            order.setStatus(20);
            int num = orderMapper.updateOrderStatusById(order);
            /*if(num>0){

            }*/
        }
        //--将支付的信息进行存储：payInfo
        PayInfo payInfo = new PayInfo();
        payInfo.setUserId(order.getUserId());
        payInfo.setOrderNo(order.getOrderNo());
        payInfo.setPayPlatform(1);
        payInfo.setPlatformStatus(tradeStatus);
        payInfo.setPlatformNumber(params.get("trade_no"));

        payInfoMapper.insert(payInfo);

        return JSONData.buildSuccess();
    }

}
